 sbtl 'prodos kernel loader'
*
********* see rev note #45/57 **********
*
*proldr equ *
* ldx #$ff ; initialize main stack pointer
* txs  ; to $ff.
*************************************
*
****************** see rev note #57 *********
*
 jmp prostart ; normal boot entry point....
 inc setuprts ; setup and rts entry point....
prostart equ *
*********************************************
 lda unit ;get boot device number.
 sta bunit ;save it for later 'prefix'
 jsr greet ;put up greeting message.
 ldx itpldr ;move interpreter loader to $800
 ldy itpldr+1
 jsr reloc
 bcs m48k ;branch if error
*
proldr1 equ *
 ldy #0
 lda #$ff ;make sure there is 
 sta $bfff ; at least 48k.
 eor $bfff
 sec
*********** branch widened- see rev note #62 ***********
 bne nogood0 ;branch if not.
 sta $bfff ;try again. once may have been luck!
 lda $bfff
*********** branch widened- see rev note #62 ***********
 bne nogood0 ;hitch to hitch
 lda romin
 jsr whchrom ;get preliminary system configuration
 bcs m48k ;branch if apple /// emulation
 lda apple ;test for 48k configuration
 and #$20 ;by testing for 64k plus.
 bne m64k ;branch if >48k
m48k jmp nogood ;must have at least 64k
m64k ldx ver64k ;now move/relocate whatever we got.
 ldy ver64k+1
 jsr reloc
 lda kversion ;get current revision number
 sta xdosver ;  and save it for directory use
*********** label added    see rev note #62 ***********
nogood0 equ * ;hitch to nogood jump
 bcs nogood1 
 lda romin
 ldx $fbb3 ;look for //e family
 cpx #6
 bne id1
 lda #$e0 ;phylum check on high 2 bits
 bit $fbc0 ;another approved location
 php ;save the results from the bit
 lda apple
 and #$37 ;mask off bits 7,6 and 3
 plp ;get results back
 bvc set3 ;//c or //x
 bmi set7 ;branch if //e
set3 php ;save the results from the bit again
 ora #$8 ;set bit 3 on
 plp
 bpl mach2 ;branch if //c
 ora #$40
 bpl savemach ;always...
mach2 inc cflag-licode+lodintrp ; make it easy to see if we're on //c later
 bvs savemach
set7 ora #$80
savemach sta apple
*
************ see rev note #50 **********
*
 lda romin ; enable rom for cortland id routine.
 sec ; carry will determine if cortland or not.
 jsr $fe1f ; rts in all a //'s prior to cortland
 bcs itsaiie ; branch if really a //e.
 inc cortland ; set loader's cortland flag!
*
************ see rem note #62 **********
*
* if setuprts is zero, zero out os.boot for appletalk.
*  (setuprts reflects whether we're prodos 8 regular or running with
*  the p16 shell.
*
 lda setuprts
 bne itsp8
**** the os.boot value is hardwired to $e100bd ****
****  and the dfb defines a 65816 sta absolute long ****
 dfb $8f,$bd,$00,$e1 ;zero is already in acc
itsp8 equ *
*
****************************************
*
itsaiie equ *
****************************************
id1 equ *
 lda bunit ;place boot devnum in globals.
 sta bbunit
 sta lstdev
 jsr devsrch ;finish setting up globals.
 lda bbunit
 sta lstdev
 jsr lc1in
 ldx tclkstuff ;and set up clock.
 ldy tclkstuff+1
 jsr reloc
nogood1 bcs nogood2 ;give up any time we got problems.
*
*  dispatcher 1 must go in bank 2 of language card
*    in a 64k or larger system.
*
 lda machid
 and #$20
 cmp #$20
 bne chkram ;not 64k or greater 
 lda #>calldisp
 sta jspare+1 ;put dispatcher relocater address
 lda #<calldisp ;  into jspare vector.
 sta jspare+2
 lda ramin2
 lda ramin2 ;switch in bank 2
 ldx dspstuff ; relocate dispatcher and rwts
 ldy dspstuff+1 ; drivers to main lc, b2.
 jsr reloc
******************** see rev note #38 **********************
* -------------------- see rev note 20 -------------------------
* ldx busstuff ;set up bus driver
* ldy busstuff+1
* jsr reloc
* --------------------------------------------------------------
************************************************************
 lda #$ee ;nonsense byte to distinguish bank 2
 sta $d000
 jsr lc1in ;switch bank 1 back in
 bcc chkram
nogood2 jmp nogood
*
* test for 128k so ram disk can be installed
*
chkram lda machid
 and #$30
 eor #$30
 ifeq os-prodos
 bne noramdsk ;branch if less than 128k system
 fin
 ifeq os-ednet
 beq ramdsk ; branch if its a 128k machine...
 sta romin ; otherwise system death since
 jsr home ; ednet requires 128k.
 ldy #no.aux.msg.len-1
showit lda no.aux.msg,y ; 
 sta qscrn,y ;
 dey  ;
 bpl showit ;
die.here jmp die.here ; and hang...
*
 msb on
no.aux.msg equ *
 asc '*** ednet requires 128k ram memory  ***'
no.aux.msg.len equ *-no.aux.msg
 msb off
*
*
ramdsk equ * 
 fin
*
*
************ see rev note #45 *************
*
 ldx #$ff ; x used to init aux sp to $ff.
 php  ; save interrupt status
 pla  ; in a reg.
 sei  ; no interrupts for safety sake.
 sta $c009 ; swap in aux lc & zp & stack.
 stx $101 ; init aux sp to $ff.
 sta $c008 ; back to main lc, zp, and stack.
 pha  ; restore
 plp  ; interrupt status.
*******************************************
 sta int3rom ;make sure internal slot 3 rom is in
 jsr ram.1 ;go install ramdisk
*
*
*  now check for interrupt vector.  if vector <$d000 then we
*    have new roms and should re-point vector in language card to
*    rom vector and set a flag byte.  in vector is >$d000, reset
*    flag byte and do nothing.
*
noramdsk equ *
 lda romin1 ;switch in rom 
 ldy irqvect
 ldx irqvect+1 ;get hi byte of irq vector
*
*--------------------- see rev note #29 ------------------------
*
* the jsr lc1in was moved here from after the bcs chk4card so the
* sta irqflag is written to the proper bank.
*
 jsr lc1in ;put the lc,b1 for r/w back now!
*
 cpx #$d0 ;is it >$d000 (old roms)
 lda #0 ;anticipate not
 bcs chk4card ;  but branch if they are old roms
 sta $c009 ;swap aux lc, zpg and stack
 lda #$ff ;set aux stack pointer at $ff
 sta $101 ;  while we're here.
 stx irqvect+1
 sty irqvect ;save rom vector in aux lang. card
 sta $c008 ;swap in main lc, zpg and stack
 stx irqvect+1
 sty irqvect ;save rom vector in main lang. card
 lda #1 ;set irqflag to show new roms
chk4card sta irqflag
*
********** see rev note #61 ****************
********** see rev note #50 ****************
*
 lda #0
 sta cortflag ;assume we're not on a cortland
 lda cortland ; are we running on a cortland?
 beq nocort ; if not branch, and muck w/slot 3!
 inc cortflag ;make it a one if we're on cortland
 jmp docard
nocort equ *
*
********************************************
*
* ------------------- see rev note 19 ------------------------------
*  check for a rom in slot 3.  switch in internal $c300 firmware
*    if no rom seen.
*
 sta int3rom ;start with internal firmware switched in
 lda sltbyt ;get slots rom pattern
 and #8 ;mask off all but slot 3
 bne isromin3 ; branch if there is rom in slot three.
 jmp noslot3rom ; continue with boot....
isromin3 equ *
*
* we've seen a rom in slot 3.  is it an external, identifiable 
*   80-col card with interrupt routines?  if so, enable it.  if not,
*   switch in the internal $c300 firmware.
*
 sta slot3rom ;switch in slot 3 rom
 lda $c305 ;1st generic terminal card id byte
 cmp #$38
 bne hitswtch ;branch if not a terminal card.
 lda $c307 ;2nd generic terminal card id byte
 cmp #$18
 bne hitswtch ;branch if not a terminal card.
 lda $c30b ;3rd generic terminal card id byte
 cmp #$01
 bne hitswtch ;branch if not a terminal card.
 lda $c30c ;is it an apple 80-col card compatible?
 and #$f0 ;mask off lo nibble
 cmp #$80 ; and check for $8n   
 bne hitswtch ;branch if not an 80-col card.
 lda machid ;get the machine id
 and #$c8
 cmp #$c0 ;is is a //+?
 beq docard ;branch if it is.
 lda $c3fa ;check for interrupt handler routine
 cmp #$2c ; in the magic $c3fa spot.
 beq docard ;branch if interrupt handler is there!
hitswtch sta int3rom ;internal $c300 rom
*
* verify that the card in the aux slot is actually there.
*
 sta $c001 ;80-store
 sta $c055 ;page2
 lda #$ee
 sta $400
 asl a
 asl $400
 cmp $400
 bne maybe ;branch if not there
 lsr a
 lsr $400
 cmp $400
maybe sta $c054 ;main memory
 sta $c000 ;80-store off
 beq docard ;branch if card is there
 lda machid ;get machine id byte
 and #$fd ;mask off 80-col bit
 bne docard1 ;always..
*
* ok, the card's good.  leave it enabled and update the machid.
*
docard lda machid ;get machine id byte
 ora #2 ;turn bit 2 on to show 80-col card
docard1 sta machid
* --------------------------------------------------------------
*
******** see rev note #50 **********
*
noslot3rom equ *
 lda cortland ; are we running on a cortland?
 beq notcortland ; branch if not.
 lda #$4c ; enable clock routine by
 sta $bf06 ; putting a jmp in front of clock vector.
 ldx cclkstuff ; now set up for relocating
 ldy cclkstuff+1 ; the cortland clock driver.
 jsr reloc ; and relocate it.
******* see rev note #58 ********
 lda machid ; denote clock present in machid byte!
 ora #1 ; bit 0 set to 1.
 sta machid ; 
notcortland equ *
**********************************
*
********************* see rev note #57 **********
*
 lda setuprts ; get value of setup entry point flag...
 beq norts ; branch if normal boot...
 lda romin ; make sure the rom is in for consistancy...
 rts ; return to the caller at the setup entry point. ($2003)
setuprts db 0 ; 0->normal boot; <>0->return.
norts equ *
*************************************************
*
* now set prefix to boot device.
*
 jsr gopro ; first 'online'(was labled bootpfx,#en3)
 dfb onlyne
 dw olparm
 bne nogood ;branch if problems.
 lda pbuf+1 ;get volume name length.
 and #$f ;strip devnum.
 beq nogood ;branch if error.
 clc ;add 1 for leading '/'
 adc #1
 sta pbuf ;save prefix length.
 lda #$2f ;place leading '/' in pbuf.
 sta pbuf+1
 jsr gopro ;set prefix.
 dfb prefix
 dw prparm
 bne nogood ;branch if problems.
 tax ;acc = 0 after successful mli call
 stx dst
 ldy #2 ;read directory into buffer starting
 lda #$c ;  at $c00
rdbdir sta dst+1 
 sta dbbufr+1 ;(using a pointer in zero page also)
 sty dbblok 
 stx dbblok+1 
 jsr gopro 
 dfb idbrd ;block read
 dw dbprms 
 bne nogood 
 ldy #3 ;get next block number from link
 lda (dst),y
 tax
 dey
 ora (dst),y ;if both bytes are the same i.e. 0, 0
 beq edbrd ; then no more blocks of directory
 lda (dst),y
 tay
 lda dst+1
 clc
 adc #2 ;add $200 to buffer pointer until buffer
 cmp #$14 ; points past $13ff.
 bcc rdbdir ;if ok, read next block
edbrd equ *
 jmp lodintrp ;all is well, load interpreter!!!
 skp 2
qscrn equ $5a9 
 skp 2 
nogood sta romin ;make sure rom is there. 
 jsr home ;clear video.
 ldy #meslen ;print message centered on screen.
prmess lda errmess,y
 sta qscrn,y
 dey
 bpl prmess
hang jmp hang
*
 msb on
meslen equ 30 
errmess asc "RELOCATION/  CONFIGURATION ERROR" 
*
olparm dfb $02
bunit dfb $60
 dw pbuf+1
 skp 1
prparm dfb $01
 dw pbuf
 skp 1
dbprms dfb $03
bbunit dfb $00
dbbufr dw $00
dbblok dw $00
*
*
 page 
czero equ $00
cmove equ $01
cradd equ $03
crloc equ $04
cdone equ $ff
at.load.addr equ $4000 ; atalk file will load here. (*#en3*)
 skp 1
itpldr dw tablitp ;table for relocation of interp loader.
ver64k dw tabl64 
tclkstuff dw rlclk64
dspstuff dw dsp64
*
********* see rev note #50 ********
*
cclkstuff dw cortclock ; address of cortland clock move table.
cortland dfb 0 ; cortland existance flag initially zero!
***********************************
 ifeq os-ednet
atrelptr dw at.rel.tbl ; address of atalk driver relocater table.
 fin
*
*  code move tables are explained in file reloc.
*  
tablitp dfb cmove ; move interpreter loader code & tables. 
 dw lodintrp ;code is address independent. 
 dw pclen
 dw licode 
*
pg3tbl dfb cmove
* ------------------- see rev note 15 --------------------------
auxgo equ $3d6 ;entry point to aux lc driver call routine
*
 dw auxgo ;was $3f0
 dw $002a ; and $0010
* --------------------------------------------------------------
 dw pg3stuf
 skp 1
 dfb cmove
 dw look
 dw 2
 dw dst
 skp 1
 dfb cmove ;move 128k test to zero page
 dw tst128
 dw end128
 dw strt128
 skp 1
 dfb cdone
 page
dsp64 dfb cmove
 dw $d100 ;(lang card bank 2)
 dw $0300 ;3 pages
 dw sel.0
*
****** see rev note #50 *******
*
* ifeq os-prodos
*bus db cmove ; move the atp drivers to mlc, b2.
* dw $d400 ; starting at $d400.
* dw $0c00 ; 3k of it.
* dw bus.0 ; load time address.
* fin
*
* -------------------- see rev note #en1 -----------------------
 ifeq os-ednet
 dfb cmove
 dw $d400 ; relocate rwts routines to $d400,b2
 dw $0700 ; 7 pages of it.
 dw xrw.0 ; where it is at load time.
 fin
* --------------------------------------------------------------
 dfb cdone
*
************** see rev note #en3 ******************
*
 ifeq os-ednet
at.rel.tbl db cmove ; move atalk driver table.
 dw $d000 ; relocate to $d000, alc,b1(+b2 if needed)
 dw $0000 ; adjusted at run time...
 dw at.load.addr ; location of code at load time.
 db cdone ; end of relocation table.
 fin
***************************************************
 page
****************************************************
* the following table is for moving the 64k version of
* the mli to its execution address.
****************************************************
*
********************* see rev note #38 *********************
*
tabl64 dfb cmove ; relocate the interrupt/break/reset
 dw inthandler ; handler and associated vectors.
 dw $0065 ; number of bytes to relocate.
 dw mli.3 ; source address of code to relocate.
*************************************************************
 skp 2
 dfb cmove ;move preset 64k version of globals
 dw globals
 dw $0100
 dw mli.1 
 skp 2 
 dfb czero ;clear buffers/workspace
 dw orig 
 dw $700
 skp 2 
 dfb cmove ;move 64k version of mli to language card.
 dw orig1 ; see #45..put rwts in lc b2 to make mli.2
 ifeq os-prodos
 dw $2100 ; mli length.
 fin
 ifeq os-ednet
 dw $2800 ; mli length + space from moved rwts.
 fin
 dw mli.2 ;from address it was loaded at.
 skp 2 
*
 ifeq os-prodos
 dfb cmove ;move 64k version of
 dw rwts ; disk ii routines
 dw $0700
 dw xrw.0
 fin
 skp 1
 dfb cdone ;clock moved later.
 skp 2
rlclk64 dfb cmove ;lastly move/relocate thunderclock
 dw tclk.in ; whether needed or not.
 dw $007d 
 dw tclock.0
 skp 1
 dfb crloc ;adjust slot addresses.
 dw tclk.in
 dw $0069 
 dw tclk.in
 dfb 0 
clock64 equ *+2
 dfb $c1,$c1,$00 ;last changed by devsrch to correct slot#.
 skp 1
 dfb cdone ;end of relocations.
*
********** see rev note #50 *********
*
cortclock dfb cmove ; cortland clock relocating table.
 dw tclk.in ; destination address.
 dw $7d ; length of 125 bytes.
 dw cclock.0 ; source load address of driver.
 dfb cdone ;
***********************************
 page
errbuf equ $56
gointerp equ $2000
iscrn equ $7a8
idxl equ $10
entlen equ $c23 
*
*
****************** see rev note #56 *************
*
* let's load and jsr to the appletalk configuaration file "atinit"
* if it is found.  if it is not found, just continue with the loading
* and running of the ".system" file.
*
licode equ *
 jsr gopro ; make a get file info call to make
 db getfileinfo ; atinit file is there and is 
 dw gfi.list ; of the proper file type.
 bcc gfi.ok ; branch if call successful...
 cmp #$46 ; was error file not found?
 beq loadint ; branch if so and continue with interp load...
 jmp atloaderr ; otherwise fatal i/o error in loading atinit file
gfi.ok equ *
 lda gfi.type ; now see if atinit file is of proper type...
 cmp #$e2 ; is it the correct file type?   
 bne atloaderr ; error if wrong file type!
 jsr gopro ;open atinit file.
 dfb iopen
 dw atopen ; parameter list...
 bne atloaderr ; branch if error...
 jsr gopro ;get file's length
 dfb igeof
 dw efparm
 bne atloaderr ; branch on error...
 lda eof+2 ;make sure file will fit.
 bne atloaderr ; branch if too big...
 lda eof+1
 cmp #$98 ;max size is 38k
 bcs atloaderr ; branch if too big...
 sta rdlen+1
 lda eof
 sta rdlen ;read entire file.
 jsr gopro
 dfb iread
 dw rdparm
 bne atloaderr ; branch if too big...
 jsr gopro
 dfb iclos
 dw clparm
 bne atloaderr ; branch on error....
*
 lda romin ; put rom on line for atinit....
 jsr $2000 ; call the atinit routine to set up appletalk stuff.
loadint equ *
 jmp goloadint ; go execute the .system file!
*
atloaderr equ * ; fatal error if trouble loading atinit file..
 ldx aterr ; load length of error msg.
aterrlp lda aterr,x
 sta iscrn,x
 dex
 bne aterrlp
aterrhang beq aterrhang ; hang. couldn't load atinit file....
aterr str 'UNABLE TO LOAD ATINIT FILE'
gfi.list equ *-licode+lodintrp
 db $a ; parameter count.
 dw atinitname ; pointer to file name.
 db 0 ; access
gfi.type equ *-licode+lodintrp
 db 0 ; file type.
 ds 13,0 ; space for rest of parameters...
*
atopen equ *-licode+lodintrp
 db 3 ; parameter count.
 dw atinitname ; pointer to "atinit" file name.
 dw $1400 ; address of i/o buffer.
 db 1 ; reference number hard coded since no other files.  
*
atinitname equ *-licode+lodintrp
 str "atinit" ; name of appletalk config file.
*
goloadint equ *-licode+lodintrp
*********************************************
 lda #$0c ;search directory already
 sta idxl+1 ; in memory between $c00 & $13ff.
 lda #4 ;start 1 entry past header.
 bne addeln ;always...
*
nxentr lda idxl ;calc next entry posn.
addeln clc
 adc entlen ;bump to next entry address.
 sta idxl
 bcs pgecros ;branch if page cross.
 adc entlen ;test for end of block.
 bcc nocros ;branch if definitely not page cross.
 lda idxl+1
 lsr a ;end of block?
 bcc nocros ;branch if not.
 cmp #9 ;end of directory?
 beq noint1 ;branch if no interpreter file.
 lda #4 ;reset index to first entry in next block.
 sta idxl
pgecros inc idxl+1 ;bump to next page.
nocros ldy #$10 ;first off, check file type.
 lda #$ff ;must be prodos sys file.
 eor (idxl),y
 bne nxentr ;branch if not.
 tay ;else check to see if active.
 lda (idxl),y
 beq nxentr ;branch if deleted file.
 and #$f ;strip file 'kind'.
 sta name ;save name's length.
*
**************** see rev note #en3 ***************
*
 ifeq os-ednet
 ldy atflg ; has atalk already been loaded?
 beq at.done ; yes, so branch.
 cmp #at.name.len ; is the file name the right length?
 bne nxentr ; no, so branch and check next entry.
 tay  ; could be, so now make sure it is.
tst.atalk equ * ; do the file names match?
 lda (idxl),y ;
 ora #$80 ; set hi bit for comparison...
 cmp at.name-1,y ; is it a match?
 bne nxentr ; no, so check next entry.
 dey  ; 
 bne tst.atalk ; go chech next char for match.
 jsr load.atalk ; go load the appletalk driver file.
 jsr setup.atalk ; move and setup the atalk drivers.
 lda #<gointerp ; put the load address for the interp back
 sta rdparm+3 ; in the read parms. (low byte assumed 0)
 dec atflg ; signify atalk now loaded.
 jmp lodintrp ; now proceed with loading interp.
at.done equ *
 fin
**********************************************************
 cmp #8 ;must be at least 'x.system'
 bcc nxentr ;otherwise, ignore it.
 bcs skip2 ;branch always...
noint1 beq nointrp ;(branch extender)
*
skip2 tay ;compare last 7 characters for '.system'.
 ldx #$6
lkintrp lda (idxl),y
 eor iterp,x
 asl a
 bne nxentr ;branch if something else.
 dey
 dex
 bpl lkintrp
 skp 1
load.atalk equ *-licode+lodintrp ; (*********** en3 ************)
 ldy #0 ;move name to pathname buffer.
mvintrp iny 
 lda (idxl),y
 sta name,y
 ora #$80 ;make it printable in case of error.
 sta iomess+$11,y
 cpy name ;all characters moved?
 bne mvintrp
 lda #$a0 ;save a space after name.
 sta iomess+$12,y
 tya ;update error message length.
 adc #$13 ;(carry was set)
 sta ierlen
 skp 1
 jsr gopro ;open interpreter file.
 dfb iopen
 dw opparm
 bne badlod
 jsr gopro ;get file's length
 dfb igeof
 dw efparm
 bne badlod
 lda eof+2 ;make sure file will fit.
 bne toolong
 lda eof+1
 cmp #$98 ;max size is 38k
 bcs toolong
 sta rdlen+1
 lda eof
 sta rdlen ;read entire file.
 jsr gopro
 dfb iread
 dw rdparm
 beq goclos ;branch if sucessful read.
 cmp #errbuf ;memory conflict?
 beq toolong
 bne badlod ;report i/o error.
goclos jsr gopro
 dfb iclos
 dw clparm
 bne badlod ;(branch never, we hope).
*
**************** see rev note #en3 ****************
*
 ifeq os-ednet
 lda atflg ; is atalk being loaded?
 beq goint ; no, so branch.
 rts  ; yes, so return and load the interp!
goint equ *
 fin
***************************************************
* if we are booting on a //c and an escape is in the keyboard buffer
* then clear it so we dont interfere with start application
* (pizza accelerator chip requires ESC to shift speed down)
 lda cflag-licode+lodintrp ;booting on a 2c?
 beq going ; branch if not
 lda $c000 ; fetch last key in board (pending or not)
 cmp #$9b ; ESCAPE character? (with bit 7 on)
 bne going ; branch if not
 sta $c010 ; clear keyboard strobe
going equ *
 lda romin
 jmp gointerp
cflag dfb $00 ; a one if an apple 2 c          
nointrp equ *
*
*********** see rev note #en3 ********
*
 ifeq os-ednet
 lda atflg ; is atalk being loaded?
 beq nitp ; no, so it is the interp not found.
 jmp no.atalk ; yes, and we can't find it!
nitp equ *
 fin
**************************************
 ldx #$27 ;report no interpreter.
nitrp lda nomess,x
 sta iscrn,x
 dex
 bpl nitrp
 bmi hang10
*
badlod ldy ierlen ;center the bad news.
 lda #$27
 sec
 sbc ierlen
 lsr a
 adc ierlen
 tax
bdlod1 lda iomess,y
 sta iscrn,x
 dex
 dey
 bpl bdlod1
 bmi hang10
*
toolong ldy #$1e
tlong1 lda lgmess,y
 sta iscrn+5,y
 dex
 bpl tlong1
hang10 bmi hang10 
*
nomess equ *-licode+lodintrp 
 asc '**  UNABLE TO FIND A ".SYSTEM" FILE  ** ' 
lgmess equ *-licode+lodintrp 
 asc '**  SYSTEM PROGRAM TOO LARGE  **'
iomess equ *-licode+lodintrp 
 asc '** UNABLE TO LOAD X.SYSTEM *********' 
ierlen equ *-licode+lodintrp 
 dfb 0
 skp 2
opparm equ *-licode+lodintrp
 dfb $03
 dw name
 dw $1400 
 dfb $01
 skp 1
efparm equ *-licode+lodintrp
 dfb $02
 dfb 01
eof equ efparm+2
 dfb 0,0,0
 skp 1
rdparm equ *-licode+lodintrp
 dfb $04
 dfb $01
 ifeq os-ednet
 dw at.load.addr ; changed back to $2000 at runtime.(*en3*)
 fin
 ifeq os-prodos
 dw $2000
 fin
rdlen equ rdparm+4 
 dw $0000
 dw $0000
 skp 1
clparm equ *-licode+lodintrp
 dfb 01
 dfb 00
 skp 1
 skp 1
iterp equ *-licode+lodintrp
 asc '.SYSTEM'
*
* note: atflg must be here so it also will get relocated!
*
 ifeq os-ednet
atflg equ *-licode+lodintrp
 db 1 ; <>0 --> loading atalk drivers
 fin
*
pclen equ *-licode
*
***************** see rev note #en3 *****************
*
 ifeq os-ednet
setup.atalk equ *
*
 sta $c009 ; switch in aux lc (bank 1 in already).
 lda eof+1 ; check if necessary to overlap to bank 2.
 cmp #$3f ; allow only $3fe4 bytes in alc, b1.
 beq check.low ; go see if low byte exceeds limit.
 bcs needs.b2 ; branch if bank 2 is needed.
 bcc one.chunk ; branch if it fits in one chunk.
check.low lda eof ;
 cmp #$e5 ; does the low byte exceed the limit?
 bcs needs.b2 ; branch if it does.
one.chunk lda eof ; move low # of bytes to relocate.
 sta at.rel.tbl+3 ; store in relocate table.
 lda eof+1 ;
 sta at.rel.tbl+4 ;
 jsr reloc.at ; move up the drivers.
 jmp copy.at.tbl ; 
needs.b2 lda #$e4 ; relocate first $3fe4 bytes.
 sta at.rel.tbl+3 ;
 lda #$3f ; 
 sta at.rel.tbl+4 ;
 jsr reloc.at ; move 'um out..
 lda eof ; now calculate overlap going into bank 2.
 sec  ;
 sbc #$e4 ; subtract low bytes..
 sta at.rel.tbl+3 ; and save low byte overlap.
 lda eof+1 ; subtract hi bytes..
 sbc #$3f ;
 sta at.rel.tbl+4 ; and save overlap.
 sta ramin2 ; switch in bank 2.
 jsr reloc.at ; go move overlap.
*
*
* copy the atalk entry point table up into the main lc.
*
copy.at.tbl equ *
 sta $c008 ; switch back to main lc.
 jsr lc1in ; and make sure bank 1 is in.
 ldx #32 ; 32 bytes in address table.
copytbl lda at.load.addr-1,x ; 
 sta atalktbl-1,x ; file, to the beginning of the mli (file
 dex  ; xdosmli).
 bne copytbl ; 
*
* now do an open atp driver call to initialize the driver and 
* bring up the appletalk interface.
*
 sei  ; no interrupts during driver init.      
 jsr gopro ;
 db $42 ; appletalk command number.
 dw at.open.list ; open driver parameter list pointer.
 bcc open.ok ; branch if open was ok.
 jmp at.open.err ; otherwise system error death time...
open.ok cli  ; allow processor to get interrupted again
*
* note that the appletalk interrupt handler is internal to prodos 
* and is resident in the file xdosmli.
*
* now the atalk printer hook must be set up to get to the rpm stub.
*
 lda at.slot ; $cn where n = atalk card slot number.
 tax  ; screenhole offset is also $cn...
 sta $3b8,x ; atalks cards 1st screen hole = $cn.
 lda #>rpm.entry-1 ; get low addr byte of rpm.stub routine.
 sta $6b8,x ; store in atalk card's 7th screen hole.
 lda #<rpm.entry-1 ; get hi addr byte of rpm.stub routine.
 sta $738,x ; store in atalk card's 8th screen hole.
 rts  ; set up for atalk complete!
*
reloc.at equ *
 ldx atrelptr ; now go and relocate the 
 ldy atrelptr+1 ; appletalk drivers...
 jsr reloc ;
 rts  ; and return.
*
at.open.err equ *
 sta romin ; rom in.
 jsr home ; clear video.
 ldy #atmsglen-1
badnews lda atmsg,y ; print "unable to open appletalk driver"
 sta qscrn,y ;
 dey  ;
 bpl badnews
freeze bmi freeze ; and hang.....
*
no.atalk equ *
 sta romin ; rom in.
 jsr home ; clear video.
 ldy #no.at.msg.len-1
badnews1 lda noatalkmsg,y ; print "unable to find appletalk driver"
 sta qscrn,y ;
 dey  ;
 bpl badnews1
freeze1 bmi freeze1 ; and hang.....
*
atmsg equ *
 asc '*** UNABLE TO OPEN APPLETALK DRIVER ***'
atmsglen equ *-atmsg
*
noatalkmsg equ *
 asc '*** UNABLE TO FIND APPLETALK DRIVER ***'
no.at.msg.len equ *-noatalkmsg
*
at.open.list db 1 ; token length of prodos parameter list.
 db 1 ; atalk open driver command number.
at.slot db 0 ; 0 has driver return $cn location of card here.
 db 1 ; driver will return node number here.
at.int.handler dw $0000 ; address of drivers's interrupt routine.
 dw $0000 ; address of direct driver entry (using x,y etc.).
*
at.name equ *
 asc 'ATALK.DRIVERS'
at.name.len equ *-at.name
*
 fin
*
*****************************************************
 skp 2 
*
pg3stuf equ * ;this stuff goes on page 3
* ------------------- see rev note 15 --------------------------
*
* locate between vectors in page 3 starting at $3d6
*
*  note: since this is treated as a subroutine from the mli,
*        nothing may use the stack in main ram area!!
*
*  x = 5 from calling routine to move parameter bytes in the call
lp1 equ * ;address after relocation = $3d6
 sta $c008 ;swap in main z.p. & stack
 lda $42,x ;get the parameter bytes
 sta $c009 ;switch in aux stack & z.p.
 sta $42,x ;save them in aux zero page
 dex
 bpl lp1
*
* at this time, a jsr is no good since we have the wrong stack pointer
*  the first, and last thing a ram based driver must do is take care
*  of the stack pointers saved in $100 & $101 of alt stack.
*
* this operational address (after relocation) is $3e3.  it must be
*   patched to a jmp $d100 when the ram based driver is installed.
*
 lda #$28 ;no device connected error
 sec ;show an error
*
comebak equ * ;ram drivers in aux lc must jmp back to here
 sta $c008
 rts ;swap main z.p. & stack, and return
 dw ramdrvr ;vector addr for patching into global page
 ds 4,0 ;spare bytes to align following vectors to $3f0
* --------------------------------------------------------------
 dw m.break ;brk vector
 dw m.reset ;reset vector
 dfb $5a ;power-up byte
 jmp m.and ;'&' vector
 jmp m.ctl.y ;ctrl-y vector
 jmp m.nmi ;nmi vector
 dw irqent ;interrupt vector to global page
 skp 2
lc1in equ * ;swap lc bank1 in
 lda ramin
 lda ramin
 rts
 page
whchrom lda #0 ;assume standard apple ii first.
 sta apple
 ldx $fbb3 ;look at the approved location...
 cpx #$38 ;apple ii? (actually is it autostart rom?) 
 beq muchram ;branch if it is..
 lda #$80 ;else try for apple iie.
 cpx #6
 beq muchram
 lda #$40 ;if that fails, try ii+.
 cpx #$ea ;must be one of these values...
 bne whatsit
 ldx $fb1e ;if it passes as ii+, then
 cpx #$ad ; it might be /// in emulation.
 beq muchram
 lda #$d0 ;mark it as 48k /// emulation!
 cpx #$8a ; if it passes the test.
 bne whatsit ;branch always, well, maybe.
nsm sec ;48k not allowed so apple ///
 rts ;  emulation is not sufficient memory 
whatsit lda #$02 ;machine unknown if we land here.
 sta (dst),y 
 bne finram ;branch always 
 skp 1
muchram sta apple ;save rom id.
 jsr lc1in ;test for the presents of 'language'
 lda #$aa ; card ram.
 sta $d000
 eor $d000 ;if it is there, result is zero.
 bne nsm ;branch if it is not.
 lsr $d000 ;else check twice just to be sure.
 lda #$55
 eor $d000
 bne nsm
 lda #$20 ;indicate at lc ram available.
is64k ora apple
finram jmp tst128 ;go test for 128k.
 skp 1
tst128 equ $80 ;use zpage for this routine 
strt128 sta apple ;save accumulated value.
 bpl not128 ;branch if sure it's less than 128k.
 skp 1
 lda #$ee ;first try storing in aux mem
 sta $c005 ;write to aux while on main zp
 sta $c003 ;set to read aux ram
 sta $c00 ;check for sparse mem mapping
 sta $800
 lda $c00 ;see if sparse memory -same value 
 cmp #$ee ;1k away 
 bne noaux 
 asl $c00 ;may be sparse mem so change value 
 asl a ;& see what happens  
 cmp $c00
 bne noaux 
 cmp $800
 bne auxmem
noaux sec  ;sparse mapping so no aux mem
 bcs back
auxmem clc  ;there is aux mem
back sta $c004 ;switch  back to write main ram
 sta $c002 ;switch back main ram read
 bcs not128 ;branch if not 128k
 lda apple ;else update identity of machine.
 ora #$30 ;indicate 128k present.
 sta apple
 skp 1
not128 lda look+1 ;futs with pointer for apple test.
 sec
 sbc #$05 ;should result in $fb if zpage is ok. 
 sta look+1 
 bcs *+4 ;(to the clc)
 dec look
 clc
 rts
end128 equ *-strt128 ;byte count for routine move to zpage.
